
#pragma once
#ifndef TEST_PROJECT_RASP_SIMU_H
#define TEST_PROJECT_RASP_SIMU_H

//目标模拟模块使用说明
//1、SetEchoLen			设置数据中回波长度，用以申请计算空间，请确保回波长度能覆盖数据
//2、SetBeamAmpFile		设置波束方向图文件指针  文件为二进制文件，格式为：(int)点数个数N+ N个std::complex<float>类型的系数矩阵
//3、SetTargetNum		设置目标数量。目前仅支持最大为2个目标
//4、SetFrPt				设置脉冲重复周期		单位：us
//5、SetFrFs				设置采样带宽			单位：MHz
//6、SetFrNum			设置脉冲个数
//7、SetSubFrFre			设置子发射频率		单位：MHz
//8、SetSubFrFs			设置子脉冲采样带宽	单位：MHz
//9、SetSubFrPt			设置子脉冲重复周期	单位：us
//10、SetSubFrPw			设置子脉冲时宽		单位：us
//11、SetSubFrBw			设置子脉冲信号带宽	单位：MHz
//12、SetSubFrType		设置子脉冲信号类型	0-正线性调频，1-负线性调频 2- 三角调频 3-非线性调频，4-二相编码，5-四相编码，其它为点频信号
//13、SetTargetRCS1		设置目标1的RCS		单位：dB
//14、SetTargetRCS2		设置目标2的RCS		单位：dB
//15、SetTargetRCSType1	设置目标1的起伏类型	0-Swerling0，1-Swerling1，2-Swerling2，3-Swerling3，4-Swerling4
//16、SetTargetRCSType2	设置目标2的起伏类型	0-Swerling0，1-Swerling1，2-Swerling2，3-Swerling3，4-Swerling4
//17、SetTargetRange1	设置目标1的距离		单位：m
//18、SetTargetRange2	设置目标2的距离		单位：m
//19、SetTargetVel1		设置目标1的速度		正-向站，负-背站，单位:m/s
//20、SetTargetVel2		设置目标2的速度		正-向站，负-背站，单位:m/s
//21、SetNoiseRcs		设置噪声的RCS			单位：dB
//22、DataProcess		计算函数：DataIn为输入值 本模块不需要输入值 DataOut为输出值  该函数目前支持std::complex<float>类型的输出 其他类型暂不支持
//						输出结果为波形数据，数据长度具体跟参数设置有关

#include <complex>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <logger.h>
#include <random>
#include <cblas.h>
#include <sys/time.h>
#include <cstring>

#define MaxNoiseLen 2000000

#define  MaxSubFrNum   3 * 10
#define  MaxScatterNum 12

#define C_Speed            299792458.458
#define Pi                3.1415926
#define BeamPointNum    20001
#define BeamInterval    0.0001
#pragma pack(1)

typedef struct DBF_RBEAM_STRUCT {
    unsigned int uRBeamNo;            //波束编号
    unsigned int uRBeamType;        //0-正常和，1-水平差，2-俯仰差，3-匿影，4-辅助，5-无效波束，其它..
    float fRBeamAzi;                //波束指向方位（阵面坐标系），单位：弧度 相对值
    float fRBeamEle;                //波束指向俯仰（阵面坐标系），单位：弧度 相对值
    bool SubFrFlag[MaxSubFrNum];    //波束接收子脉冲的标识，仅针对波束类型uRBeamType：0、1、2有效；0-不接收，1-接收
} DBF_RBEAM_STRUCT;

typedef struct PARA_BEAMCOE_STRUCT {
    std::complex<float> *STBeamFormingAmp;    //发射赋形波束俯仰方向图
    std::complex<float> *SAziTBeamAmp;        //发射笔形波束水平方向图
    std::complex<float> *SEleTBeamAmp;        //发射笔形波束俯仰方向图
    std::complex<float> *SAziRBeamAmp;        //接收和波束水平方向图
    std::complex<float> *SEleRBeamAmp;        //接收和波束俯仰方向图
    std::complex<float> *DAziRBeamAmp;        //接收水平差波束方向图
    std::complex<float> *DEleRBeamAmp;        //接收俯仰差波束方向图
    std::complex<float> *SLBAziBeamAmp;        //匿影波束水平向方向图
    std::complex<float> *SLBEleBeamAmp;        //匿影波束俯仰向方向图
    std::complex<float> *SimuMalloc;        //缓存指针
} PARA_BEAMCOE_STRUCT;

class Rasp_Simu {
public:
    Rasp_Simu();

    ~Rasp_Simu();

    void UnInit();

    int DataProcess(void *DataIn, int inLen, void *DataOut, int outLen);

public:
    bool SetEchoLen(unsigned int len);

    bool SetBeamAmpFile(const void *beamampfile);

    bool SetTargetNum(unsigned int TNum);

    bool SetFrPt(float fpt);

    bool SetFrFs(float ffs);

    bool SetFrNum(unsigned int frnum);

    bool SetSubFrFre(float SubFrFre);

    bool SetSubFrFs(float SubFrFs);

    bool SetSubFrPt(float SubFrPt);

    bool SetSubFrPw(float SubFrPw);

    bool SetSubFrBw(float SubFrBw);

    bool SetSubFrType(unsigned int SubFrType);

    bool SetTargetRCS1(float TargetRCS1);

    bool SetTargetRCS2(float TargetRCS2);

    bool SetTargetRCSType1(unsigned TargetRCSType1);

    bool SetTargetRCSType2(unsigned TargetRCSType2);

    bool SetTargetRange1(float TargetRange1);

    bool SetTargetRange2(float TargetRange2);

    bool SetTargetVel1(float fTargetVel1);

    bool SetTargetVel2(float fTargetVel2);

    bool SetNoiseRcs(float noisercs);

    bool SetFlagAddNoise(int flag);

private:

    int CalcuEchoLen();

    void CalcuRBeamCoe(DBF_RBEAM_STRUCT *RBeam, PARA_BEAMCOE_STRUCT BeamCoePara, unsigned int uBwBeamNum,
                       float fFrFre, float fTBeamAzi, float fTBeamEle, float fTargetAzi, float fTargetEle,
                       std::complex<float> *RBeamCoe);

    int ComplexCAdd(std::complex<float> *Ain, int ModifyAddr, int ComplexLen, std::complex<float> *Cout);

    void
    ComplexCPMul(std::complex<float> Ain, std::complex<float> *Bin, unsigned int DataLen, std::complex<float> *Cout);

    std::complex<float> ComplexExp(float in);

    void ComplexMExp(float in, unsigned int DataLen, std::complex<float> *out);

    void ComplexMul(std::complex<float> Ain, std::complex<float> Bin, std::complex<float> *Cout);

    void
    ComplexPMul(std::complex<float> *Ain, std::complex<float> *Bin, unsigned int DataLen, std::complex<float> *Cout);

    int Gen_WorkSig(std::complex<float> *pOut);

    int Gen2PnSig(float fApm, int DelayLen, int CodeNum, int Coderepmat, std::complex<float> *pOut);

    int Gen4PnSig(float fApm, int DelayLen, int CodeNum, int Coderepmat, std::complex<float> *pOut);

    int GenNLFMSig(float fApm, int DelayLen, float Pw, float Bw, float Fs, int ModuDir, float *ACoe,
                   std::complex<float> *pOut, int ACoe_Len);

    int GenPFSig(float fApm, float Pw, float Fs, float F0, int DelayLen, std::complex<float> *pOut);

private:
    int Gen_STargetEchoSig(float rcs, unsigned int rcs_type, float TargetRange, float fTargetVel);

    std::complex<float> *MTargetEchoSig;
    unsigned int Echo_Len;
    unsigned int BeamCoe_Len;
    PARA_BEAMCOE_STRUCT BeamCoePara{};
    unsigned int ehobacklen;
    std::complex<float> *TFdCoeAddr;
    std::complex<float> *WorkSig;
    std::complex<float> *EchoData0Addr;
    std::complex<float> *pOut;
    double rcsswerling[2000]{};
    int sendcount;
    unsigned int STargetNum;
    unsigned int m_CpiNum;
    bool b_AllfrSame;
    float m_fFrPt;
    float m_fFrFs;
    unsigned int m_uBwBeamNum;
    unsigned int m_uFrNum;
    DBF_RBEAM_STRUCT m_RBeam{};
    float m_fSubFrFre;
    float m_fSubFrFs;
    float m_fSubFrPt;
    float m_fSubFrPw;
    float m_fSubFrBw;
    unsigned int m_uSubFrType;


    float fTargetRCS_1;
    float fTargetRCS_2;
    unsigned int uTargetRCSType_1;
    unsigned int uTargetRCSType_2;
    float fTargetRange_1;
    float fTargetRange_2;
    float fTargetVel_1;
    float fTargetVel_2;

    float m_uExpectTime;
    int m_uTarDataLen{};
    float m_NoiseRcs;
    unsigned int target_count;
    float fTargetNowRange1{};
    float fTargetNowRange2{};
    float fTargetNowVel1{};
    float fTargetNowVel2{};

    int FlagAddNoise = 1;

    std::complex<float> *pNoiseData = nullptr;
};

#pragma pack()

#endif //TEST_PROJECT_RASP_SIMU_H
